home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / glibc108.zip / glibc108 / sysdeps / posix / system.c < prev    next >
C/C++ Source or Header  |  1994-05-18  |  4KB  |  146 lines

  1. /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. #include <sys/wait.h>
  24. #include <signal.h>
  25. #include <sys/types.h>
  26.  
  27.  
  28. #ifndef    HAVE_GNU_LD
  29. #define    __environ    environ
  30. #endif
  31.  
  32. #define    SHELL_PATH    "/bin/sh"    /* Path of the shell.  */
  33. #define    SHELL_NAME    "sh"        /* Name to give it.  */
  34.  
  35. /* Execute LINE as a shell command, returning its status.  */
  36. int
  37. DEFUN(system, (line), register CONST char *line)
  38. {
  39.   int status, save;
  40.   pid_t pid;
  41.   struct sigaction sa, intr, quit;
  42. #ifndef WAITPID_CANNOT_BLOCK_SIGCHLD
  43.   sigset_t block, omask;
  44. #endif
  45.  
  46.   if (line == NULL)
  47.     return 1;
  48.  
  49.   sa.sa_handler = SIG_IGN;
  50.   sa.sa_flags = 0;
  51.   __sigemptyset (&sa.sa_mask);
  52.  
  53.   if (__sigaction (SIGINT, &sa, &intr) < 0)
  54.     return -1;
  55.   if (__sigaction (SIGQUIT, &sa, &quit) < 0)
  56.     {
  57.       save = errno;
  58.       (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
  59.       errno = save;
  60.       return -1;
  61.     }
  62.  
  63. #ifndef WAITPID_CANNOT_BLOCK_SIGCHLD
  64.  
  65. /* SCO 3.2v4 has a bug where `waitpid' will never return if SIGCHLD is
  66.    blocked.  This makes it impossible for `system' to be implemented in
  67.    compliance with POSIX.2-1992.  They have acknowledged that this is a bug
  68.    but I have not seen nor heard of any forthcoming fix.  */
  69.  
  70.   __sigemptyset (&block);
  71.   __sigaddset (&block, SIGCHLD);
  72.   save = errno;
  73.   if (__sigprocmask (SIG_BLOCK, &block, &omask) < 0)
  74.     {
  75.       if (errno == ENOSYS)
  76.     errno = save;
  77.       else
  78.     {
  79.       save = errno;
  80.       (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
  81.       (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
  82.       errno = save;
  83.       return -1;
  84.     }
  85.     }
  86. #define UNBLOCK    __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL)
  87. #else
  88. #define UNBLOCK 0
  89. #endif
  90.  
  91.   pid = __vfork ();
  92.   if (pid == (pid_t) 0)
  93.     {
  94.       /* Child side.  */
  95.       CONST char *new_argv[4];
  96.       new_argv[0] = SHELL_NAME;
  97.       new_argv[1] = "-c";
  98.       new_argv[2] = line;
  99.       new_argv[3] = NULL;
  100.  
  101.       /* Restore the signals.  */
  102.       (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
  103.       (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
  104.       (void) UNBLOCK;
  105.  
  106.       /* Exec the shell.  */
  107.       (void) __execve (SHELL_PATH, (char *CONST *) new_argv, __environ);
  108.       _exit (127);
  109.     }
  110.   else if (pid < (pid_t) 0)
  111.     /* The fork failed.  */
  112.     status = -1;
  113.   else
  114.     /* Parent side.  */
  115. #ifdef    NO_WAITPID
  116.     {
  117.       pid_t child;
  118.       do
  119.     {
  120.       child = __wait (&status);
  121.       if (child <= -1)
  122.         {
  123.           status = -1;
  124.           break;
  125.         }
  126.     } while (child != pid);
  127.     }
  128. #else
  129.     if (__waitpid (pid, &status, 0) != pid)
  130.       status = -1;
  131. #endif
  132.  
  133.   save = errno;
  134.   if ((__sigaction (SIGINT, &intr, (struct sigaction *) NULL) |
  135.        __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL) |
  136.        UNBLOCK) != 0)
  137.     {
  138.       if (errno == ENOSYS)
  139.     errno = save;
  140.       else
  141.     return -1;
  142.     }
  143.  
  144.   return status;
  145. }
  146.